package cn.edu.nuaa.aadl2.generatorC.template
import org.osate.aadl2.SubprogramType
import org.osate.aadl2.CalledSubprogram
import org.osate.aadl2.SubprogramImplementation
import org.osate.aadl2.SubprogramClassifier
import cn.edu.nuaa.aadl2.generatorC.utils.Tools
import static extension cn.edu.nuaa.aadl2.generatorC.utils.StringUtils.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.FeatureTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.PropertyTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.DataTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.AnnexTemplate.*
import org.osate.aadl2.PropertyAssociation
import org.osate.aadl2.SubprogramCall
import org.osate.aadl2.SubprogramSubcomponent
import org.osate.aadl2.impl.DefaultAnnexSubclauseImpl
import cn.edu.nuaa.aadl2.signal2Code.Signal2CFrontEndCmd
import cn.edu.nuaa.aadl2.generatorC.utils.SubProgramProperties

/*
 * Subprogram template
 * subprogram as subcomponent applies to(process implementation ,thread implementation subprogram implementation)
 * subprogram as subprogram calls
 * */
class SubprogramTemplate {

	def static create(CalledSubprogram cs,String folder) {
		switch cs {
			SubprogramSubcomponent: '''«cs.create(folder)»'''
		}
	}

	def static create(SubprogramSubcomponent subprogram1,String folder) {
		var sp=new SubProgramProperties()
		var subprogram = subprogram1.classifier
		switch subprogram {
			SubprogramType: '''
				«Tools.createFile(folder,"_subprogramType_"+subprogram.name.convert+".h",subprogram.head(folder).toString)»
				«Tools.createFile(folder,"_subprogramType_"+subprogram.name.convert+".c",subprogram.template(folder,sp).toString)»
			'''
			SubprogramImplementation: '''
				«Tools.createFile(folder,"_subprogramImpl_"+subprogram.name.convert+".h",subprogram.head(folder).toString)»
				«Tools.createFile(folder,"_subprogramImpl_"+subprogram.name.convert+".c",subprogram.template(folder,sp).toString)»
			'''
		}
	}

	def static include(CalledSubprogram subprogram) {
		switch subprogram {
			SubprogramType: '''
				#include "_subprogramType_«subprogram.name.convert».h"
			'''
			SubprogramImplementation: '''
				#include "_subprogramImpl_«subprogram.name.convert».h"
			'''
		}
	}

	def static init(CalledSubprogram subprogram) {
		switch subprogram {
			SubprogramType: '''
				
			'''
			SubprogramImplementation: '''
				
			'''
		}
	}

	def static head(SubprogramClassifier subprogram,String folder) {
		switch subprogram {
			SubprogramType: '''
				/*Subprogram Type head file*/
				extern int «subprogram.name.convert»();
			'''
			SubprogramImplementation: '''
				/*Subprogram Implementation head file*/
				«Tools.addContent(folder,Template.systemheadfile,"#include \""+"_subprogramType_"+subprogram.name.convert+".h"+"\"")»
				extern int «subprogram.name.convert»(«subprogram.dealWithSubprogramParas.toString.clearspace»);
			'''
		}
	}

	def static dealWithSubprogramParas(SubprogramClassifier subprogram) '''
		«subprogram.allFeatures.dealRequireDataAccess.toString.clearspace.convertNo2Low.removeLastChar»
	'''

	def static dealWithSubprogramParasOnly4ParaName(SubprogramClassifier subprogram) '''
		«subprogram.allFeatures.dealRequireDataAccessOnly4ParaName.toString.clearspace.convertNo2Low.removeLastChar»
	'''

	def static template(SubprogramClassifier subprogram,String systemFolder,SubProgramProperties sp) {
		switch subprogram {
			SubprogramType: '''
				/*Subprogram Type c file*/
				«Template.head»
				#include "«Template.systemheadfile»"	
				«IF subprogram.allPropertyAssociations!=null»
					«FOR PropertyAssociation pa : subprogram.allPropertyAssociations»
						«pa.getIncludeOfSubprogram»
					«ENDFOR»	
				«ENDIF»							
				int «subprogram.name.convert»()
				{
					«IF subprogram.allPropertyAssociations!=null»
						«FOR PropertyAssociation pa : subprogram.allPropertyAssociations»
							«pa.property2Code»
						«ENDFOR»	
					«ENDIF»
					return 1;
				}
			'''
			SubprogramImplementation: '''
				«IF subprogram.allPropertyAssociations!=null»
						«subprogram.allPropertyAssociations.dealWithSubprogramProperties(sp)»
				«ENDIF»
				/*Subprogram Implementation c file*/
				«Template.head»
				#include "«Template.systemheadfile»"
				«IF sp.sourceLanguage!="Signal"»
				//#include "«sp.sourceText.replaceAll(".sig",".h")»"
				«ENDIF»
				«FOR sub : subprogram.ownedDataSubcomponents»
					«sub.template»
				«ENDFOR»
				
					«IF subprogram.getSubprogramCalls!=null»
						«FOR SubprogramCall sc : subprogram.getSubprogramCalls»
							«IF sc.calledSubprogram!=null»
								«sc.calledSubprogram.create(systemFolder)»
								«IF sc.calledSubprogram instanceof SubprogramClassifier»
									«sc.calledSubprogram.include»
								«ENDIF»
							«ENDIF»
						«ENDFOR»
					«ENDIF»	
				int «subprogram.name.convertNo2Low»(«subprogram.dealWithSubprogramParas.toString.clearspace»)
				{
					«IF sp.sourceLanguage!="Signal"»
						«IF subprogram.getSubprogramCalls!=null»
							«FOR SubprogramCall sc : subprogram.getSubprogramCalls»
								«IF sc.calledSubprogram!=null»
									«sc.calledSubprogram.call»
								«ENDIF»
							«ENDFOR»
						«ENDIF»					
						«IF subprogram.ownedAnnexSubclauses.size > 0»
							«FOR  annexSubclause : subprogram.ownedAnnexSubclauses»
								«IF subprogram.isCalledByWd»
									«val delay=subprogram.getDelay»
									int WDID=wdCreate();
									wdStart(WDID,«delay»,(FUNCPTR)«subprogram.name.convertNo2Low»_BehaviorAnnex,«subprogram.dealWithSubprogramParasOnly4ParaName.toString.clearspace»);
								«ELSE»
									«subprogram.name.convertNo2Low»_BehaviorAnnex(«subprogram.dealWithSubprogramParasOnly4ParaName.toString.clearspace»);
								«ENDIF»
							«ENDFOR»
						«ENDIF»			
					«ELSE»
					//parameters 4 signal2C progress  «sp.sourceText» «Template.aimPath» 
					«Signal2CFrontEndCmd.exeCmd(sp.getSourceText(), Template.aimPath)»
					«sp.sourceName»(«subprogram.dealWithSubprogramParas.toString.clearspace»);			
					«ENDIF»				
					return 1;
				}
					
				«IF subprogram.ownedAnnexSubclauses.size > 0»
					«FOR  annexSubclause : subprogram.ownedAnnexSubclauses»
						«AnnexSwitch(subprogram.name.convertNo2Low,annexSubclause as DefaultAnnexSubclauseImpl,subprogram.dealWithSubprogramParas.toString.clearspace,true).toString»
					«ENDFOR»
				«ELSE»
					//TO-DO annex
				«ENDIF»
								
			'''
		}
	}

	def static callFeature(CalledSubprogram subprogram) {
		switch subprogram {
			SubprogramType: '''«subprogram.getAllFeatures.asVariables»'''
			SubprogramImplementation: '''«subprogram.type.getAllFeatures.asVariables»'''
		}
	}

	def static call(CalledSubprogram subprogram) {
		switch subprogram {
			SubprogramType: '''«subprogram.name.convert»(«IF subprogram.getAllFeatures!=null»«subprogram.getAllFeatures.asParameters»«ENDIF»);'''
			SubprogramImplementation: '''«subprogram.name.convert»(«IF subprogram.type.getAllFeatures!=null»«subprogram.type.getAllFeatures.asParameters»«ENDIF»);'''
		}
	}

	def static inThread(CalledSubprogram subprogram) {
		switch subprogram {
			SubprogramType: '''«subprogram.name.convert»(«IF subprogram.getAllFeatures!=null»«subprogram.getAllFeatures.asParameters»«ENDIF»);'''
			SubprogramImplementation: '''«subprogram.name.convert»(«IF subprogram.type.getAllFeatures!=null»«subprogram.type.getAllFeatures.asParameters»«ENDIF»);'''
		}
	}
}
